﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using ScoreHelper.Properties;

namespace ScoreHelper
{
    public class DomProxy
    {
        public enum OperationStatus
        {
            Error = -100,
            Ready = 0,
            Login = 1,
            LoginFailed = -1,
            FillFactor = 2,
            FillScore = 3,
            Saved = 4,
            Printing = 5,
            Finished = 10,
            ChangePassword = 11,
            Ignored = 99,
            Quit = 100
        }

        public event EventHandler OnTemplateClick;
        public event EventHandler OnBrowseFile;
        private OperationStatus curStatus;
        private OperationStatus lastAvailableStatus;
        private string[] ignoreUrls;
        private string[] printUrls;
        
        private int printIndex = 0;
        private int printStatus = 0;
        private string courseName;
        private string courseNum;
        private string serialNum;
        private HtmlElement frmScore;
        private HtmlElement frmOption;

        public OperationStatus CurStatus
        {
            get { return curStatus; }
        }

        public OperationStatus LastStatus
        {
            get { return lastAvailableStatus; }
        }

        public string[] IgnoreUrls
        {
            get { return ignoreUrls; }
        }

        public string[] PrintUrls
        {
            get { return printUrls; }
        }

        public string NextPrintUrl
        {
            get 
            {
                printIndex++;
                if (printIndex >= printUrls.Length || printIndex < 0)
                    return "";
                return printUrls[printIndex]; 
            }
        }

        public int PrintIndex
        {
            get 
            {
                return printIndex;
            }
        }
        public int PrintStatus
        {
            get { return printStatus; }
            set { printStatus = value; }
        }

        public HtmlElement FrmScore
        {
            get { return frmScore; }
        }

        public string CourseNum
        {
            get { return courseNum; }
        }
        public string SeralNum
        {
            get { return serialNum; }
        }
        public string CourseName
        { 
            get { return courseName; } 
        }
        public string User
        {
            get;
            set;
        }
        public string Password
        {
            get;
            set;
        }


        public void PreparePrint()
        {

            IEPrintSettings.Instance.MarginTop = "0.39370";
            IEPrintSettings.Instance.MarginBottom = "0.39370";
            IEPrintSettings.Instance.MarginLeft = "0.27559";
            IEPrintSettings.Instance.MarginRight = "0.27559";
            IEPrintSettings.Instance.SaveSettings();
            printIndex = -1;
            Application.DoEvents();
        }

        public void Print(WebBrowser wb)
        {
            //while (wb.ReadyState != WebBrowserReadyState.Complete)
            //    Application.DoEvents();
            SHDocVw.WebBrowser axWb = (SHDocVw.WebBrowser)(wb.ActiveXInstance);
            PrintStatus = 1;
            axWb.PrintTemplateTeardown += new SHDocVw.DWebBrowserEvents2_PrintTemplateTeardownEventHandler(delegate { PrintStatus = 0; });
            axWb.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER);
            while (PrintStatus > 0)
                Application.DoEvents();
            axWb.PrintTemplateTeardown -= new SHDocVw.DWebBrowserEvents2_PrintTemplateTeardownEventHandler(delegate { PrintStatus = 0; });
        }

        public void EndPrint()
        {
            IEPrintSettings.Instance.Reset2Default();
        }

        public void SetFrmScore(HtmlDocument Doc)
        {
            if (Doc == null)
                return;
            frmScore = Doc.Forms[Settings.Default.ScoreFormElem];
        }
        public HtmlElement FrmOption
        {
            get { return frmOption; }
        }
        public void SetFrmOption(HtmlDocument Doc)
        {
            if (Doc == null)
                return;
            frmOption = Doc.Forms[Settings.Default.ScoreOptFormElem];
            string[] chkNames = Settings.Default.ScoreChkElems.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < chkNames.Length; i++ )
                frmOption.All[chkNames[i]].AttachEventHandler("onclick", delegate
                {
                    Uri mainUrl = Doc.Window.Parent.Frames[Settings.Default.FrameMain].Url;
                    if (mainUrl.ToString().IndexOf(Settings.Default.ScoreUrl, StringComparison.CurrentCultureIgnoreCase) < 0)
                        return;
                    string url = Settings.Default.ScoreUrl + "?" + string.Format(Settings.Default.CourseUrlQuery, courseNum, serialNum, User);
                    foreach (HtmlElement link in Doc.Links)
                    {
                        if (link.GetAttribute("href").IndexOf(url, StringComparison.CurrentCultureIgnoreCase) >= 0)
                        {
                            link.InvokeMember("click");
                            break;
                        }
                    }
                });
        }

        private List<string> courses;
        //获取所有课程
        public void SetCourses(System.Windows.Forms.HtmlDocument fDoc)
        {
            if (courses == null)
                courses = new List<string>();
            else if(courses.Count > 0)
                courses.Clear();
            foreach (System.Windows.Forms.HtmlElement link in fDoc.Links)
            {
                string url = link.GetAttribute("href");
                if (string.IsNullOrEmpty(url))
                    continue;
                url = url.ToLower();
                if (url.IndexOf(Settings.Default.ScoreUrl) > 0)
                {
                    courses.Add(link.InnerText.Trim());
                }
            }
        }
        public List<string> Courses
        {
            get { return courses; }
        }

        public DomProxy()
        {
            curStatus = OperationStatus.Ready;
            ignoreUrls = Settings.Default.IgnoreUrls.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            frmScore = null;
            frmOption = null;
        }

        public bool SaveUserInfo(HtmlDocument fDoc)
        {
            if (fDoc == null || fDoc.Forms.Count < 1)
                return false;
            HtmlElement frm = fDoc.Forms[0];

            HtmlElement elem = frm.All[Settings.Default.UserElem];
            if (elem == null)
                return false;
            User = elem.GetAttribute("value");

            elem = frm.All[Settings.Default.PwdElem];
            if (elem == null)
                return false;
            Password = elem.GetAttribute("value");
            return true;
        }

        public bool SetSavedUser(string UserID, string Password, HtmlDocument fDoc)
        {
            if (fDoc == null || fDoc.Forms.Count < 1)
                return false;
            HtmlElement frm = fDoc.Forms[0];
            
            HtmlElement elem = frm.All[Settings.Default.UserElem];
            if(elem == null)
                return false;
            elem.SetAttribute("value", UserID);

            // no auto login
            elem = frm.All[Settings.Default.PwdElem];
            if (elem == null)
                return false;
            elem.SetAttribute("value", Password);

            if (frm.GetAttribute("action").IndexOf("jym2005") < 0)
            {
                Random rnd = new Random();
                frm.SetAttribute("action", frm.GetAttribute("action") + "?jym2005=" + ((((DateTime.Now.Millisecond * 9301 + 49297) % 233280) / (233280.0) + rnd.Next()) * 9301));   
            }
           
            //frm.InvokeMember("submit");
            return true;
        }

        public OperationStatus ParseStatus(HtmlDocument Doc, string cUrl)
        {
            if(curStatus != OperationStatus.Ignored)
                lastAvailableStatus = curStatus;
            curStatus = OperationStatus.Error;
            if (Doc == null || string.IsNullOrEmpty(cUrl))
                return OperationStatus.Error;

            cUrl = cUrl.ToLower();
            // 忽略列表
            foreach (string strIUrl in IgnoreUrls)
            {
                if (cUrl.IndexOf(strIUrl) >= 0)
                    return OperationStatus.Ignored;
            }

            if (cUrl.IndexOf(Settings.Default.LoginUrl) >= 0
                || cUrl.IndexOf(Settings.Default.StartUrl) >=0) // 等待登录
                curStatus = OperationStatus.Ready;
            else if(cUrl.IndexOf(Settings.Default.LoginedUrl) >= 0) // 登录成功->准备填写系数
                curStatus = OperationStatus.Login;
            else if (cUrl.IndexOf(Settings.Default.LoginFailedUrl) >= 0) // 登录失败->重新登录
                curStatus = OperationStatus.LoginFailed;
            else if (cUrl.IndexOf(Settings.Default.FactorUrlS) >= 0) // 填充成绩系数
                curStatus = OperationStatus.FillFactor;
            else if (cUrl.IndexOf(Settings.Default.ScoreUrl) >= 0)
            {
                curStatus = OperationStatus.Finished;  // 默认为完成  已提交，准备打印
                if(Doc != null)
                {
                    // 获取主窗口--跨frame的ready事件传递整个文档
                    if (Doc.Window.Frames.Count > 1)
                    {
                        Doc = Doc.Window.Frames[Settings.Default.FrameMain].Document;
                    }

                    if (Doc.All[Settings.Default.CourseNumElem] != null
                        && Doc.All[Settings.Default.CourseSerialElem] != null)
                    {
                        courseNum = Doc.All[Settings.Default.CourseNumElem].GetAttribute("value");
                        serialNum = Doc.All[Settings.Default.CourseSerialElem].GetAttribute("value");
                        courseName = courses.Find(c => c.IndexOf(courseNum + "-" + serialNum) > 0);
                        if(!string.IsNullOrEmpty(courseName))
                            courseName = courseName.Substring(0, courseName.IndexOf('('));
                    }

                    if (Doc.All[Settings.Default.ScoreInput] != null
                        && Doc.All[Settings.Default.ScoreInput1] != null) // 填充成绩
                    {
                        curStatus = OperationStatus.FillScore;
                        SetFrmScore(Doc);
                        AddBtns(Doc);
                    }
                    else  // 提交状态，获取打印用的URL
                    {
                        printUrls = new string[3];
                        printUrls[0] = new Uri(Doc.Url, string.Format(Settings.Default.PrintUrl1, courseNum, serialNum)).ToString();
                        printUrls[1] = new Uri(Doc.Url, string.Format(Settings.Default.PrintUrl2, courseNum, serialNum)).ToString();
                        printUrls[2] = new Uri(Doc.Url, string.Format(Settings.Default.PrintUrl3, courseNum, serialNum)).ToString();
                    }
                }
            }
            else if (cUrl.IndexOf(Settings.Default.QuitUrl) >= 0) // 退出
                curStatus = OperationStatus.Quit;
            else if (cUrl.IndexOf(Settings.Default.ChangePswUrl) >= 0) // 修改密码
                curStatus = OperationStatus.ChangePassword;
            else if (cUrl.IndexOf(Settings.Default.PrintUrlS1) >= 0
                || cUrl.IndexOf(Settings.Default.PrintUrlS2) >= 0
                || cUrl.IndexOf(Settings.Default.PrintUrlS3) >= 0) // 打印
                curStatus = OperationStatus.Printing;
            else if (cUrl.IndexOf(Settings.Default.LeftUrl) >= 0)
            {
                // 自动更新课程列表和记录课程选项
                // 获取主窗口--跨frame的ready事件传递整个文档
                // 添加自动修改事件

                if (Doc.Window.Frames.Count > 1)
                {
                    Doc = Doc.Window.Frames[Settings.Default.FrameLeft].Document;
                    SetFrmOption(Doc); // 选项， 并添加事件
                    SetCourses(Doc); // 所有课程
                }
                curStatus = OperationStatus.Ignored;
            }

            return CurStatus;

        }

        private void AddBtns(HtmlDocument fDoc)
        {
            HtmlElement btnTemplate = fDoc.CreateElement("INPUT");
            btnTemplate.SetAttribute("type", "button");
            btnTemplate.SetAttribute("value", "成绩单模板");
            btnTemplate.SetAttribute("title", "下载Excel成绩单模板文件");
           
            HtmlElement btnBrowse = fDoc.CreateElement("INPUT");
            btnBrowse.SetAttribute("type", "button");
            string text = "选择成绩单";
            if (!string.IsNullOrEmpty(courseName))
                text += " - " + courseName;
            btnBrowse.SetAttribute("value", text);
            btnBrowse.SetAttribute("title", "选择成绩单文件后自动开始检查格式并填充成绩");

            btnBrowse = fDoc.Body.InsertAdjacentElement(HtmlElementInsertionOrientation.AfterBegin, btnBrowse);
            HtmlElement span = fDoc.Body.InsertAdjacentElement(HtmlElementInsertionOrientation.AfterBegin, fDoc.CreateElement("SPAN"));
            span.InnerHtml = "&nbsp;&nbsp;&nbsp;&nbsp;";
            btnTemplate = fDoc.Body.InsertAdjacentElement(HtmlElementInsertionOrientation.AfterBegin, btnTemplate);

            btnTemplate.AttachEventHandler("onclick", OnTemplateClick);
            btnBrowse.AttachEventHandler("onclick", OnBrowseFile);

            HtmlElementCollection tbls = fDoc.GetElementsByTagName("TABLE");
            tbls[0].Style = "display:none;";
        }

        
    }
}
